package org.finesys.common.mp.core.utils;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.finesys.common.mp.core.annotation.QueryIgnore;
import org.finesys.common.mp.core.annotation.QueryWrappers;
import org.finesys.common.mp.core.constants.QueryWrapperConstants;
import org.finesys.common.mp.core.constants.QueryWrapperEnum;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;

import lombok.extern.slf4j.Slf4j;

/**
 * 获取查询条件工具类
 */
@Slf4j
public class QueryWrapperUtils {

    private static boolean underscoreToCamel;

    public static void setUnderscoreToCamel(boolean underscoreToCamel) {
        QueryWrapperUtils.underscoreToCamel = underscoreToCamel;
    }

    public static boolean getUnderscoreToCamel() {
        return underscoreToCamel;
    }

    /**
     * 根据传入的class对象，创建wrapper查询对象
     */
    public static <T> QueryWrapper<T> queryWrapper(T t) {
        Field[] fields = getFieldsByOrder(t.getClass());
        if (ObjectUtils.isEmpty(fields)) {
            return Wrappers.emptyWrapper();
        }
        // 查询条件集合
        List<Map<String, Object>> queryList = new ArrayList<>();
        // 排序集合
        List<Map<String, Object>> orderList = new ArrayList<>();
        // 循环判断
        for (Field field : fields) {
            //需要忽略的字段
            if (isIgnoreField(field)) {
                continue;
            }
            // 判断是否存在查询注解，并判断是否排序字段
            QueryWrappers queryWrappers = field.getAnnotation(QueryWrappers.class);
            if (queryWrappers != null) {
                if (queryWrappers.sort()) {
                    Map<String, Object> map = new HashMap<>();
                    map.put("field", field);
                    map.put("queryWrapper", queryWrappers);
                    orderList.add(map);
                }
            }
            // 获取对象的字段值
            // 权限
            boolean isAccessible = field.isAccessible();
            // 允许访问私有字段
            field.setAccessible(true);
            Object value;
            try {
                value = field.get((Object) t);
            } catch (IllegalAccessException e) {
                log.error("IllegalAccessException:获取变量值发生异常. field={}", field.toString());
                continue;
            }
            // 忽略为空的值
            if (ObjectUtils.isEmpty(value)) {
                // 还原权限
                field.setAccessible(isAccessible);
                continue;
            }
            // 判断是否存在查询注解
            if (queryWrappers != null) {
                Map<String, Object> map = new HashMap<>();
                map.put("field", field);
                map.put("queryWrapper", queryWrappers);
                map.put("value", value);
                queryList.add(map);
            } else {
                Map<String, Object> map = new HashMap<>();
                map.put("field", field);
                map.put("queryWrapper", null);
                map.put("value", value);
                queryList.add(map);
            }
            // 还原权限
            field.setAccessible(isAccessible);
        }
        // 封装对象
        if (ObjectUtils.isEmpty(queryList) && ObjectUtils.isEmpty(orderList)) {
            return Wrappers.emptyWrapper();
        }
        // 查询条件
        QueryWrapper<T> wrapper = new QueryWrapper<T>();
        //是否转换驼峰式为下划线
        boolean under = getUnderscoreToCamel();
        // 字段查询
        for (Map<String, Object> map : queryList) {
            Field filed = (Field) map.get("field");
            Object value = (Object) map.get("value");
            String columnName = filed.getName();
            QueryWrappers queryWrappers = null;
            if (map.get("queryWrapper") != null) {
                queryWrappers = (QueryWrappers) map.get("queryWrapper");
            }
            // 默认相等
            String condition = QueryWrapperEnum.EQ.getValue();
            if (queryWrappers != null) {
                condition = queryWrappers.condition();
                if (StringUtils.hasText(queryWrappers.column())) {
                    columnName = queryWrappers.column();
                } else {
                    if (under) {
                        columnName = com.baomidou.mybatisplus.core.toolkit.StringUtils.camelToUnderline(columnName);
                    }
                }
            } else {
                if (under) {
                    columnName = com.baomidou.mybatisplus.core.toolkit.StringUtils.camelToUnderline(columnName);
                }
            }
            switch (condition) {
                case QueryWrapperConstants.EQ:
                    wrapper.eq(columnName, value);
                    break;
                case QueryWrapperConstants.NEQ:
                    wrapper.ne(columnName, value);
                    break;
                case QueryWrapperConstants.GT:
                    wrapper.gt(columnName, value);
                    break;
                case QueryWrapperConstants.GTE:
                    wrapper.ge(columnName, value);
                    break;
                case QueryWrapperConstants.LT:
                    wrapper.lt(columnName, value);
                    break;
                case QueryWrapperConstants.LTE:
                    wrapper.le(columnName, value);
                    break;
                case QueryWrapperConstants.LIKE:
                    wrapper.like(columnName, value);
                    break;
                case QueryWrapperConstants.L_LIKE:
                    wrapper.likeLeft(columnName, value);
                    break;
                case QueryWrapperConstants.R_LIKE:
                    wrapper.likeRight(columnName, value);
                    break;
                case QueryWrapperConstants.N_LIKE:
                    wrapper.notLike(columnName, value);
                    break;
                case QueryWrapperConstants.NULL:
                    wrapper.isNull(columnName);
                    break;
                case QueryWrapperConstants.NOTNULL:
                    wrapper.isNotNull(columnName);
                    break;
                case QueryWrapperConstants.IN:
                    wrapper.in(columnName, value);
                    break;
                case QueryWrapperConstants.NOT_IN:
                    wrapper.notIn(columnName, value);
                    break;
            }
        }
        // 排序处理
        for (Map<String, Object> map : orderList) {
            Field filed = (Field) map.get("field");
            String columnName = filed.getName();
            String sortType = QueryWrapperConstants.ORDER_ASC;
            QueryWrappers queryWrappers = null;
            if (map.get("queryWrapper") != null) {
                queryWrappers = (QueryWrappers) map.get("queryWrapper");
            }
            if (queryWrappers != null) {
                if (StringUtils.hasText(queryWrappers.column())) {
                    columnName = queryWrappers.column();
                }else{
                     if (under) {
                        columnName = com.baomidou.mybatisplus.core.toolkit.StringUtils.camelToUnderline(columnName);
                    }
                }
                if (StringUtils.hasText(queryWrappers.sortType())) {
                    sortType = queryWrappers.sortType();
                }
            }
            if (QueryWrapperConstants.ORDER_ASC.equals(sortType)) {
                wrapper.orderByAsc(columnName);
            } else {
                wrapper.orderByDesc(columnName);
            }
        }
        return wrapper;
    }

    /**
     * 判断是否忽略该字段
     */
    public static boolean isIgnoreField(Field field) {
        String fieldName = field.getName();
        //序列化字段不需要
        if ("serialVersionUID".equals(fieldName)) {
            return true;
        }
        //如果存在忽略注解，则不进行处理
        QueryIgnore queryIgnore = field.getAnnotation(QueryIgnore.class);
        if (queryIgnore != null) {
            return true;
        }
        //如果是忽略字段无需处理
        TableField tableField = field.getAnnotation(TableField.class);
        return tableField != null && !tableField.exist();
    }

    /**
     * 获取排序后的类
     */
    public static Field[] getFieldsByOrder(Class<?> classz) {
        // 获取类的字段属性
        Field[] fields = classz.getDeclaredFields();
        // 循环处理
        for (int currentIndex = 0; currentIndex < fields.length; currentIndex++) {
            Field currentField = fields[currentIndex];
            QueryWrappers queryWrappers = currentField.getAnnotation(QueryWrappers.class);
            if (queryWrappers == null) {
                continue;
            }
            int next = currentIndex + 1;
            int minOrder = queryWrappers.sortOrder();
            int minIndex = currentIndex;
            Field minField = currentField;
            while (next < fields.length) {
                QueryWrappers queryWrappersNext = currentField.getAnnotation(QueryWrappers.class);
                if (queryWrappersNext == null) {
                    next++;
                    continue;
                }
                if (minOrder > queryWrappersNext.sortOrder()) {
                    minOrder = queryWrappersNext.sortOrder();
                    minField = fields[next];
                    minIndex = next;
                }
                next++;
            }
            // 交换
            if (minIndex != currentIndex) {
                Field curField = fields[currentIndex];
                fields[currentIndex] = minField;
                fields[minIndex] = curField;
            }
        }
        /**如果存在序列化ID，去除*/

        return fields;
    }

}
